# 使用 AssetBundle 进行资源按需加载
# 一. AssetBundle概述
AssetBundle是Unity内置的一种资源加载的方式,由于较为底层,因此对于开发而言会付出额外的精力及学习成本,同样由于过程完全可控,因此可以实现更加细粒度的控制,具体取舍视实际项目本身决定。
关于AssetBundle的使用可以参考
https://docs.unity3d.com/2021.3/Documentation/Manual/AssetBundlesIntro.html (opens new window)
对于AssetBundle中的原理实现,以及会影响性能及内存的几个详细的解释可以参考
https://blog.uwa4d.com/archives/USparkle_Addressable3.html (opens new window)
同时对于AssetBundle中比较头疼的冗余检测可以参考
https://blog.51cto.com/u_15338442/3563063 (opens new window)
可以参考一个AssetBundle的冗余检测的实现
GitHub - akof1314/AssetBundleReporter: Unity AssetBundle Reporter (opens new window)
注意:小游戏环境不支持assetbundle本地加载
# 二. AssetBundle的简单例子
# 2.1 打包
public static void Build()
{
string dst = Application.streamingAssetsPath + "/AssetBundles";
if (!Directory.Exists(dst)){
Directory.CreateDirectory(dst);
}
BuildPipeline.BuildAssetBundles(dst,
BuildAssetBundleOptions.AppendHashToAssetBundleName
| BuildAssetBundleOptions.ChunkBasedCompression
| UnityEditor.BuildAssetBundleOptions.DisableWriteTypeTree
| BuildAssetBundleOptions.None,
BuildTarget.WebGL);}
# 2.2 加载
对于本地加载AssetBundle包,由于不支持本地读取文件,因此AssetBundle.LoadFromFile等都将失效,所有加载都需要通过网络,UnityWebRequest可以参考 https://docs.unity3d.com/cn/2021.1/Manual/UnityWebRequest-DownloadingAssetBundle.html (opens new window) 主要包括
- UnityWebRequestAssetBundle.GetAssetBundle
public IEnumerator Load_AB()
{
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uriPath);
yield return request.SendWebRequest();
if (request.isHttpError)
{
Debug.LogError(GetType() + "/ERROR/" + request.error);
}
else
{
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
// ab.LoadAsset
ab.Unload(false);
}
request.Dispose();
}
- UnityWebRequest
public IEnumerator LoadAB()
{
UnityWebRequest www = new UnityWebRequest(uriPath);
DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.uri.ToString(), 0);
www.downloadHandler = handler;
yield return www.SendWebRequest();
if (www.isHttpError)
{
Debug.LogError(GetType() + "/ERROR/" + www.error);
}
else
{
AssetBundle ab = handler.assetBundle;
// ab.LoadAsset
ab.Unload(false);
}
www.Dispose();
}
# 三. 资源缓存
小游戏因其平台特殊性,需要保证加载速度,因此我们在底层对bundle文件做了缓存,开发者无须自己实现缓存。
游戏逻辑还是按照未缓存需要从网络下载去编写,插件底层会判断是否已有缓存。若未缓存则缓存此bundle;若已缓存,则返回缓存文件,实际不会发起网络请求。
资源缓存与更新的不同,会导致APP与小游戏不同的加载流程:
- 常见APP AssetBundle使用方式:
- 检查更新-->下载更新全量资源-->写入文件系统-->运行时LoadFromFile
- TapTap 小游戏 AssetBundle使用方式
- 打包ab时文件名带hash-->UnityWebRequest按需下载并使用资源
在业务侧看来:总是使用异步接口从远程下载并使用,底层资源的缓存与更新已由适配层自动完成,游戏不再直接读写文件系统。